*. Sticky notes


Falcom did a spectacular job with the coding and anime-style.

But this game is a lot of work.
Read very carefully.

; ---------------------------------------------------------------------

~116e00 = 1-bpp 16x16 font

Optimized alphabet. Resulting in unorganized kanji/tile identification.
Needs lots of filling-in work.


Coded using display lists, which means that it's a linked list of structures
that call the next item via ASM pointers.

It's best to build the tiles as 16x16. You --MIGHT-- be able to go 8x16 but it's
a risky move because of list traversal. And remember to _manually_ add data
packages to the list during overflow VWF tiles.

See the 'print.txt' file for some detailed explanation on the engine. It's
consuming confusing if you've never dealt with this before.


The tile builder goes from 1-bpp to 4-bpp using some strange bitmath.
Runs row-by-row and adds the result to the list buffer.


Flow:
Load $FFFF85A4 = display list ptr

Package #1
- ASM ptr = $0C10 / 16x16 tile DMA
- VRAM addr = TILE 16-bits
- DMA size = 16-bits (TL/TR tiles)
- TILE data = $40 bytes

Package #2
- ASM ptr = $0C10 / 16x16 tile DMA
- VRAM addr = TILE 16-bits
- DMA size = 16-bits (BL/BR tiles)
- TILE data = $40 bytes

Package #3
- ASM ptr = $0C10 / NT-A DMA
- VRAM addr = NT-SCR-A 16-bits
- DMA size = 2 (TL/TR tiles)
- TILE data = 4 bytes

Package #4
- ASM ptr = $0C10 / NT-A DMA
- VRAM addr = NT-SCR-A 16-bits
- DMA size = 2 (BL/BR tiles)
- TILE data = 4 bytes

Save $FFFF85A4 = display list ptr


Code also does NT-row adjustments and tile vram wrapping.

; ---------------------------------------------------------------------

There's around 20 scripting codes, with no real notable ones except the 32-bit
JMP/JSL embedded pointers (0C-0D). And the embedded ASM (09-0A).

All language strings run through 00:FF68 so tag that when you encounter some
hard-coded ones. FDxx-FFxx lookup the extended font table.

; ---------------------------------------------------------------------

The first problem is the rewind pointers/subroutines. Everytime you add new strings
to the dumping lists, there's a 60% chance you'll hit an embedded pointer.

And a 30% chance that it points backwards in the file - the dumper will log it as a
'*** MISS' in the output and store it in the rewind file. Run the dumper again to
catch this EMBWRITE/EMBSET pair in your script.

This basically means that either you'll need a perfect dumping file to begin with -
the way this game is structured makes it less likely. Or take note of where the new
strings begin in the redumped file and MANULLY add them to your old script file. When
there's NEW embset/embwrite pairs, you can use your own numbers (1000+) to seperate
them.

; ---------------------------------------------------------------------

Next is something called 'run-on strings'. Falcom. When the string stops, the game
runs the next string anyways. So no pointers are wasted.

But that leaves us problems that surface as weird scripting bugs - the intro
dialogue repeats post-battle or sprites wander aimlessly around the map. Then
you know you probably hit one of these.

They also like to follow embedded ASM routines in the script.

Alternatively, you can scan the file and look for 'gaps' in the address ranges.
Some are taken care of, but it's unknown whether they will interfere with future
embedded pointers.

; ---------------------------------------------------------------------

Third, we have embedded ASM that take CONTROL of the scripting flow. One such
is <ASM 0A><$00007184>.

The game will finish the script after the ASM scripting opcode. But check the 68k
file for info on this. It actually loads embedded data inside the script itself.
Data usually follows the <STOP> code.

$7184 is used to display the 'MOVE/STATUS/OPTIONS' world menu. And then moves Alfred
to his next destination, also handled as EMBEDDED DATA POINTERS.

See $33472 for an example in the dumped script file.

; ---------------------------------------------------------------------

<ASM 0A><$0003F03C> is for the battle HELP menu. Strange code that selects
the help message #1-2 based on the world+stage context.

You'll notice that option #3 is a 'random' choice. Which loads another table
of 16-bit offset pointers. Then points to the script.

With a run-on string following the above opcode.

; ---------------------------------------------------------------------

The frightening script code is the <ASM 09>.

For world #1 (bulletins A-C), the game uses embedded assembly to possibly
load a HARD-CODED LEA pointer. Or skip the conditional jump.

I couldn't detect this with the dumper (too hard). What you'll need to
do is JMP.L to your expanded ROM - the RTS will restore the proper script cursor.

My suggestion is to then use an indirect 32-bit script pointer.
So normally the script resumes at $344C2. But it can JMP to $344E9.

So if the LEA occurs, then MOVEA.l ($2FF000),A4. And at $2FF000 we have
the Atlas EMBSET(3000) pointer. At $344E9, we have the EMBWRITE(3000) command.


Sadly, this is pretty confusing to handle. I don't know how many exist.
Here's a more detailed version.

<ASM 09>
#ALIGN(2)

// This means the whole data = $0E bytes.
<$00><$0E>
<$4A><$78><$D1><$A4>
<$66><$04>
<$49><$FA><$00><$2B>
<$4E><$75>


// Branch failed - continue script here
// $344C2

<CODE 07><$2A><$00><$01>
ȂɂƂA<kanji 102><kanji c8>A<kanji 102><kanji c8>AłB

<CODE 11><$1F><ASM 0A>
#ALIGN(2)
<$00><$08><$00><$00><$73><$3A><$00><$0C><JMP 0C>

//[0344E5]
//<$00><$03><$43><$88>
#EMBSET(66)



// Branch success - rewire script here
// $344E9

// UNCOMMENT and ADD THIS NEXT LINE TO YOUR SCRIPT
//#EMBWRITE(3000)

<CODE 07><$2C><$00><$01>

AAtbh<kanji 59>`łB<LINE>
܂܂傤I



At the end of the Atlas file:
#JMP($2FF000)
#EMBSET(3000)

which will write the 32-bit pointer to $344E9.

; ---------------------------------------------------------------------

Moving up, we come to the pointer tables.

There's two main values to take note
- $CD3C = world (0..7)
- $CD3E = battle (0..4) normally


Sadly, there's many table variations. 6-byte structures. 32-bit direct.
16-bit direct. 16-bit offset. 16-bit LEA. 16-bit indirect offset.

I left the original tables and script alone. Completely. Replaced with
all 32-bit direct pointers. However, the old code/data is fused to allow
comptability and success (random choices is a notable example).

Check the new ASM mods.


You'll need to study the dump_file carefully if you want to add more
pointer tables. But I did make sure to be thorough, given the game's peculiar
nature.


So the dump file is sorted in three parts:
- main story narrative
- battle text
- hard-coded text (probably plenty I couldn't find)

True seperation. Even in your script file.

; ---------------------------------------------------------------------

Finally, this game likes to use copy protection. Checksum bomb is #1. If that's
bypassed, ROM integrity checks are placed post-battle/load game/press start. And
who don't know where.

You'll either get a RAM system error message (00:B152, 01:BEB8) which I zapped.
But the game has other locations too. The result is that it will let you know
that all of the save games got wiped as PUNISHMENT. So beware.

; ---------------------------------------------------------------------

A note on Gens states.

You can use a cheat for the world/stage numbers when starting/loading games.
This kinda allows players to skip around and see different locales. Also works
for post-victory messages and post-battle screens.


But ALWAYS save state at the WORLD screen before entering a battle. And use a
different one for battles. Because Gens doesn't seem to handle SRAM loads well.

So load the WORLD state first, then the BATTLE save. Your battle should continue
without some nasty crashes.

; ============================================================================
; ############################################################################
; ============================================================================

Atlas 1.06 is modified (nothing new since 'Super Robot Wars EX')

> #FILL( int stop_address, int file_byte )		- pads up to stop address
  #FILL( int start, stop, int file_byte )		- pads address range
  #FILL( int start, stop, int file_byte, string file )	- pads address range IN FILE

  #WARN( int warn_address )				- OKAY/BARF if PC counter >= warn_address

  #SAVEPC( string file_name )				- writes PC to file
  #LOADPC( string file_name )				- loads PC from file

  #INSERT( string file_name )				- inserts binary file at current PC

  MSB16,MSB24,MSB32,GB4xxx				- addressing modes

  #SETINDEX( int index_number, int size )		- init the index numbers
  #WRITEINDEX( int address, int index_bump )		- writes index numbers to address, # bytes
							  and auto-bumps the index #
  #WRITEINDEX( int addr, int index_bump, string file )	- writes index number to address IN FILE

  #SAVEINDEX( string file_name )			- writes INDEX # to file
  #LOADINDEX( string file_name )			- loads INDEX # from file

  #ALIGN( int byte_count )                      	- does file alignment (1,2,3,4)

  #W08BYTE( int address, int byte )			- writes byte to address (no JMP)
  #W08BYTE( int addr, int byte, string file )		- writes byte to address IN FILE (no JMP)

  #EMBCLEAR()						- erases all embedded pointers

  #SAVEPTRTABLE( PTRTABLE table, string file_name )	- writes PTRTABLE address to file
  #LOADPTRTABLE( PTRTABLE table, string file_name )	- loads PTRTABLE address from file 

  #WRITEOFS( PTRTABLE table, int offset )		- writes POINTER at an offset amount (from the table start)
